import socket
from typing import NoReturn

import numpy as np
from flask import Flask, request, jsonify, redirect, url_for
from flask_cors import CORS
import base64
import io
import threading
import sys
import time

import requests
import cv2
from yolov5 import YOLOv5
import pytesseract
from PIL import Image
import redis
lock=threading.Lock()
r = redis.Redis(host="127.0.0.1", port=6379, db=0, decode_responses=True)
if r.get("zhu")==None:
    r.set("zhu",1)
if r.get("dev1Hid")==None:
    r.set("dev1Hid","1-22")

# 加载预训练的YOLOv5模型
model = YOLOv5("./best.pt",device='0')  # 选择模型
model2 = YOLOv5("./number.pt",device='0')  # 选择模型
r.set("dev1","0")
r.set("dev1Send","0")
app = Flask(__name__)
CORS(app)

global oldNum
global status
global flag_Sta
flag_Sta=1
status=0
oldNum="00"
global oid_img_yuan_bast64
global new_img_yuan_bast64
oid_img_yuan_bast64="no"
new_img_yuan_bast64="noh"
new_img_yuan_bast64=r.get("new_img_yuan_bast64")
# 加载YOLOv5模型
#获取本机id
@app.route('/python/getLocalIpV6', methods=['GET'])
def getLocalIpV6():
    try:
        # 获取本机所有可能的地址信息
        address_info = socket.getaddrinfo('', None)

        # 过滤出IPv6地址
        ipv6_addresses = [
            f"[{info[4][0]}]"  # IPv6地址用方括号括起来，这是IPv6地址的常规表示法
            for info in address_info
            if info[0] == socket.AF_INET6 and not info[4][0].endswith('%')  # 忽略链路本地地址（带%接口号的）
        ]

        # 如果找到IPv6地址，则返回第一个（或所有，如果需要的话）
        if ipv6_addresses:
            return ipv6_addresses[2]  # 或者 return ipv6_addresses
        else:
            return "no"
    except Exception as e:
        return "no"
@app.route('/python/detect', methods=['POST'])
def detect_objects():
    global pre64
    global flag
    pre64=""
    flag=0
    s1=time.time()
    data = request.json
    base64_img = data.get('image')



    if not base64_img:
        return jsonify({'error': 'No image data provided'}), 400

        # 解码Base64图片
    img_bytes = base64.b64decode(base64_img)
    img_io = io.BytesIO(img_bytes)
    img = Image.open(img_io)
    img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)  # PIL图像是RGB，OpenCV是BGR
    cv2.imwrite('C:\\Users\\23659\Desktop\yolov5-master\yolov5-master\output.jpg', img)
    # YOLOv5预测
    results = model.predict(img)
    #results.render()  # 可视化结果（如果需要的话）



    # 准备返回的数据
    labels = []
    #print(model)
    f=0
    for *xyxy, conf, cls in reversed(results.xyxy[0]):  # 遍历结果

        if model.model.names[int(cls)]=="close":
            f=1
        if conf > 0.2:  # 设置置信度阈值
            label = {'label': model.model.names[int(cls)], 'confidence': float(conf), 'bbox': [int(xyxy[0]), int(xyxy[1]), int(xyxy[2]), int(xyxy[3])]}
            labels.append(label)
    s2=time.time()
    if f==1:
        cv2.imwrite('C:\\Users\\23659\Desktop\yolov5-master\\newimag\\'+str(time.time())+'.png', img)
    print(s2-s1)
    print(len(labels))
    return jsonify({'labels': labels})
@app.route('/python/getnum', methods=['POST'])
def str1():
    s1=time.time()
    data = request.json
    base64_img = data.get('image')

    if not base64_img:
        return jsonify({'error': 'No image data provided'}), 400

        # 解码Base64图片
    img_bytes = base64.b64decode(base64_img)
    img_io = io.BytesIO(img_bytes)
    img = Image.open(img_io)
    img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)  # PIL图像是RGB，OpenCV是BGR

    pytesseract.pytesseract.tesseract_cmd = r"D:\Program Files\Tesseract-OCR\tesseract.exe"
    text = pytesseract.image_to_string(img, lang='eng')
    return text

#数字识别
@app.route('/python/getNum_two', methods=['POST'])
def getNum_two():

    global oldNum
    global status
    global flag_Sta
    s1=time.time()
    data = request.json
    base64_img = data.get('image')



    if not base64_img:
        return jsonify({'error': 'No image data provided'}), 400

        # 解码Base64图片
    img_bytes = base64.b64decode(base64_img)
    img_io = io.BytesIO(img_bytes)
    img = Image.open(img_io)
    img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)  # PIL图像是RGB，OpenCV是BGR

    # YOLOv5预测
    results = model2.predict(img)
    results.render()  # 可视化结果（如果需要的话）

    cv2.imwrite('C:\\Users\\23659\Desktop\yolov5-master\yolov5-master\output.jpg', img)

    # 准备返回的数据
    labels = []
    #print(model)
    f=0
    for *xyxy, conf, cls in reversed(results.xyxy[0]):  # 遍历结果
        if conf > 0.4:  # 设置置信度阈值
            label = {'label': model2.model.names[int(cls)], 'confidence': float(conf), 'bbox': [int(xyxy[0]), int(xyxy[1]), int(xyxy[2]), int(xyxy[3])]}
            labels.append(label)
    s2=time.time()

    print("识别用时:"+str(s2-s1))
    print("识别结果长度:"+str(len(labels)))
    for i in range(len(labels)-1):
        for j in range(0,len(labels)-i-1):
            if labels[j]['bbox'][0]>=labels[j+1]['bbox'][0]:
                temp=labels[j];
                labels[j] = labels[j+1]
                labels[j+1] = temp

    res=""
    for i in range(len(labels)):
        res+=str(labels[i]['label'])
    print("识别出:"+res)
    if len(res)>=6:
        if res==oldNum :
            status=status+1
            if status>=3:
                flag_Sta=0
                r.set("dev1","0")
                r.set("zhu","6")
                requests.get("http://127.0.0.1:8204/Sms/api/sms/sendEmail/2365912699@qq.com/重置通知标志位?content=https://"+getLocalIpV6()+":80/python/resetSend设备进入待机模式",timeout=3)
                requests.get("http://127.0.0.1:8204/Sms/api/sms/sendTongzhi/15394980567/dev1",timeout=3)
        else:
            oldNum=res
            status=0
        flag_Sta=1
        return res
    else:
        if not len(res)==0:
            status=status+1
            if status>=3:
                flag_Sta=0
                requests.get("http://127.0.0.1:8204/Sms/api/sms/sendEmail/2365912699@qq.com/设备状态通知?content=dev1设备进入待机模式",timeout=3)
                requests.get("http://127.0.0.1:8204/Sms/api/sms/sendTongzhi/15394980567/dev1",timeout=3)
                r.set("dev1","0")
                r.set("zhu","6")
        return "None"

@app.route('/python/image')
def get_image():
    return redirect(url_for('./index.html'))

#运程控制
@app.route('/python/getNum_controlle', methods=['POST'])
def getNum_controlle():
    global new_img_yuan_bast64

    s1=time.time()
    data = request.json
    base64_img = data.get('image')
    if not base64_img:
        return jsonify({'error': 'No image data provided'}), 400
    new_img_yuan_bast64=base64_img
    r.set("new_img_yuan_bast64",base64_img)
    s2=time.time()
    print("用时："+str(s2-s1))
    return "ok"


#运程控制指令发送
@app.route('/python/getNum_zhu', methods=['POST'])
def getNum_zhu():
    global flag_Sta
    # 假设API接受JSON格式的POST请求，并且Base64字符串是JSON中的一个字段
    zhu=r.get("zhu")
    if flag_Sta==1:
        r.set("dev1","1")
    return zhu

#运程控制指令发送
@app.route('/python/setzhu', methods=['POST'])
def setzhu():
    data = request.json
    # 假设API接受JSON格式的POST请求，并且Base64字符串是JSON中的一个字段
    r.set("zhu",data.get("zhu"))
    return "ok"

def setDevStatus():
    while 1:
        r.set("dev1","0")
        time.sleep(2*60)

#检测异常并发送短信通知

def checkDevStatus():
    time.sleep(5*60)
    while 1:
        try:
            s=r.get("dev1")
            print("dev1当前状态:"+s)
            if s=="0":
                time.sleep(1*60)
                s=r.get("dev1")
                print("检测异常并发送短信通知")
                if s=="0":
                    time.sleep(1*60)
                    s=r.get("dev1")
                    if s=="0":
                        time.sleep(1*60)
                        s=r.get("dev1")
                        sen=r.get("dev1Send")
                        if s=="0" and sen=="0":
                            print("检测异常并发送短信通知发送")
                            requests.get("http://127.0.0.1:8204/Sms/api/sms/sendEmail/2365912699@qq.com/重置通知标志位?content=https://"+getLocalIpV6()+":80/python/resetSend",timeout=3)
                            requests.get("http://127.0.0.1:8204/Sms/api/sms/sendTongzhi/15394980567/dev1",timeout=3)
                            r.set("dev1Send","1")
                            r.set("zhu","6")
        except Exception as e:
            print("异常信息发送异常")

        time.sleep(20)
#检测异常并发送短信通知标志重置
@app.route('/python/resetSend', methods=['GET'])
def resetSend():
    r.set("dev1Send","0")
    r.set("dev1","1")
    r.set("zhu","1")
    return "ok"

#检测异常并发送短信通知标志重置
@app.route('/python/getDev1Hid', methods=['GET'])
def getDev1Hid():
    return r.get("dev1Hid")

#获取设备运行状态
@app.route('/python/getDevStatus', methods=['GET'])
def return_devStatus():
    return r.get("dev1")

#获取页面bast64数据
@app.route('/python/yuanBast64', methods=['GET'])
def yuanBast64():
    return new_img_yuan_bast64

#获取本机id
@app.route('/python/getLocalIp', methods=['GET'])
def getLocalIp():
    ip = socket.gethostbyname(socket.gethostname())
    return ip


#获取本机id
@app.route('/python/getHidList', methods=['GET'])
def getHidList():
    lock.acquire()
    resul=[]
    try:
        id=r.get("dev1Hid")
        resul_tem={"product":"hua_dev1","id":id}
        resul.append(resul_tem)
        lock.release()
    except Exception as e:
        lock.release()
    return resul



#HID点击动作指令
@app.route('/python/HidActionClick', methods=['POST'])
def HidActionClick():
    try:
        lock.acquire()
        data = request.json
        print(data)
        # 设置请求的URL和其他参数
        url = 'http://127.0.0.1:8080/api/click'
        headers = {'Content-Type': 'application/json'}

        # 发送POST请求
        response = requests.post(url, json=data, headers=headers,timeout=120)
        print(response)
        lock.release()
    except Exception as  e:
        lock.release()
    return "send click ok"

#HID滑动动作指令
@app.route('/python/HidActionslip', methods=['POST'])
def HidActionslip():
    try:
        lock.acquire()
        data = request.json
        print(data)
        # 设置请求的URL和其他参数
        url = 'http://127.0.0.1:8080/api/swipe'
        headers = {'Content-Type': 'application/json'}

        # 发送POST请求
        response = requests.post(url, json=data, headers=headers,timeout=120)
        print(response)
        lock.release()
    except Exception as e:
        lock.release()
    return "send swipe ok"


#开门狗
t = threading.Thread(target=setDevStatus, args=())
t.daemon=True
t.start()

#开门狗
t1 = threading.Thread(target=checkDevStatus, args=())
t1.daemon=True
t1.start()
if __name__ == '__main__':

    app.run(host='0.0.0.0', port=5000)